<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>星级评分之第五种实现方式</title>
    <style>
      body, ul, li {
        margin: 0;
        padding: 0;
      }
      li {
        list-style-type: none;
      }
      .rating, .rating-display {
        background: url(img/twoStar.jpg) repeat-x;
      }
      .rating {
        position: relative;
        width: 300px;
        margin: 100px auto;
      }
      .rating-display {
        width: 112px;
        height: 56px;
        background-position: 0 -56px;
      }
      .rating-mask {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
      }
      .rating-item {
        display: block;
        float: left;
        width: 56px;
        height: 56px;
        cursor: pointer;
      }
    </style>
    <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  </head>
  <body>
    <div id="rating" class="rating">
      <!--<div class="rating-display"></div>
      <ul class="rating-mask">
        <li class="rating-item"></li>
        <li class="rating-item"></li>
        <li class="rating-item"></li>
        <li class="rating-item"></li>
        <li class="rating-item"></li>
      </ul>-->
    </div>

    <script>
      var rating = (function() {
        // 策略模式
        var strategies = {
          entire: function() {
            return 1;
          },
          half: function() {
            return 2;
          },
          quarter: function() {
            return 4;
          }
        }

        // 评分
        var Rating = function(el, optios) {
          this.$el = $(el);
          this.opts = $.extend({}, Rating.DEFAULTS, optios);

          if(!strategies[this.opts.mode]) {
            this.opts.mode = 'entire';
          };
          this.ratio = strategies[this.opts.mode]();

          this.opts.total *= this.ratio;
          this.opts.num *= this.ratio;

          this.itemWidth = 60 / this.ratio;
          this.displayWidth = this.opts.num * this.itemWidth;
        };
        Rating.DEFAULTS = {
          mode: 'entire',
          total: 5,
          num: 2,
          readOnly: false,
          select: function() {},
          chosen: function() {}
        };
        Rating.prototype.init = function() {
          this.buildHTML();
          this.setCSS();
          if(!this.opts.readOnly) {
            this.bindEvent();
          }
        };
        Rating.prototype.buildHTML = function() {
          var html = '';
          html += '<div class="rating-display"></div><ul class="rating-mask">';
          for(var i = 0; i < this.opts.total; i++) {
            html += '<li class="rating-item"></li>';
          }
          html += '</ul>';
          this.$el.html(html);
        };
        Rating.prototype.setCSS = function() {
          this.$el.width(this.opts.total * this.itemWidth);
          this.$display = this.$el.find('.rating-display');
          this.$display.width(this.displayWidth);
          this.$el.find('.rating-item').width(this.itemWidth);
        };
        Rating.prototype.bindEvent = function() {
          var self = this;
          self.$el.on('mouseover', '.rating-item', function() {
            var count = $(this).index() + 1;
            self.$display.width(count * self.itemWidth);

            (typeof self.opts.select === 'function') && self.opts.select.call(this, count, self.opts.total);

            self.$el.trigger('select', [count, self.opts.total]);
          }).on('click', '.rating-item', function() {
            var count = $(this).index() + 1;
            self.displayWidth = count * self.itemWidth;

            (typeof self.opts.chosen === 'function') && self.opts.chosen.call(this, count, self.opts.total);

            self.$el.trigger('chosen', [count, self.opts.total])
          }).on('mouseout', function() {
            self.$display.width(self.displayWidth);
          });
        };
        Rating.prototype.unbindEvent = function() {
          this.$el.off();
        };
        var init = function(el, option) {
          var $el = $(el);
          var rating = $el.data('rating');
          if(!rating) {
            $el.data('rating', (rating = new Rating(el, typeof option === 'object' && option)));
            rating.init();
          }
          if(typeof option === 'string') {
            rating[option]();
          }
        };

        // jQuery插件
        $.fn.extend({
          rating: function(option) {
            return this.each(function() {
              init(this, option);
            })
          }
        });

        return {
          init: init
        };
      })();

      $('#rating').rating({
        mode: 'half',
        total: 8,
        num: 3,
        readOnly: false,
        chosen: function(count, total) {
          console.log(123)
          $('#rating').rating('unbindEvent');
        }
      })
    </script>
  </body>
</html>